import java.util.*;

public class day1 {
    /**
     * DP18 滑雪
     * https://www.nowcoder.com/practice/36d613e0d7c84a9ba3af3ab0047a35e0?tpId=230&tqId=39760&ru=/exam/oj
     */
    public static int n,m;
    public static int[][] arr = new int[101][101];

    // 优化：记忆化搜索
    public static int[][] dp = new int[101][101];

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();

        for(int i = 0;i < n;i++) {
            for(int j = 0;j < m;j++) {
                arr[i][j] = in.nextInt();
            }
        }
        int ret = 0;
        for(int i = 0;i < n;i++) {
            for(int j = 0;j < m;j++) {
                // 以每一个位置为起点的时候的最大递减长度
                // 需要取最大的一个数
                ret = Math.max(ret,dfs(i,j));
            }
        }
        System.out.println(ret);
    }

    public static int[] dx = {0,0,1,-1};
    public static int[] dy = {1,-1,0,0};

    public static int dfs(int i,int j) {
        if(dp[i][j] != 0) { // 记忆化搜索优化
            return dp[i][j];
        }

        int len = 1;
        for(int k = 0;k < 4;k++) {
            int x = i + dx[k];
            int y = j + dy[k];
            if(x >= 0 && x < n && y >= 0 && y < m && arr[x][y] < arr[i][j]) {
                len = Math.max(len,dfs(x,y) + 1);
            }
        }
        dp[i][j] = len; // 记忆化搜索优化
        return len;
    }



    /**
     * NC51 合并k个已排序的链表
     * https://www.nowcoder.com/practice/65cfde9e5b9b4cf2b6bafa5f3ef33fa6?tpId=196&tqId=37081&ru=/exam/oj
     */
    public class ListNode {
        int val;
        ListNode next = null;
        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode mergeKLists (ArrayList<ListNode> lists) {
        // 使用堆的方法，先把每个链表的头结点放入到堆中，每次取最小值，当取出之后把对应的节点的后一个节点放入到队列中，进行循环
        PriorityQueue<ListNode> heap = new PriorityQueue<>((v1,v2) -> {
            return v1.val - v2.val;
        }); // 小根堆
        int n = lists.size();
        for(int i = 0;i < n;i++) {
            if(lists.get(i) != null) {
                // 放入每个链表的头结点
                heap.offer(lists.get(i));
            }
        }

        ListNode ret = new ListNode(-1);
        ListNode cur = ret;
        while(!heap.isEmpty()) {
            // 取出堆顶数据
            ListNode tmp = heap.poll();
            cur.next = tmp;
            cur = cur.next;

            if(tmp.next != null) {
                heap.offer(tmp.next);
            }
        }
        return ret.next;
    }



    /**
     * NC114 旋转字符串
     * https://www.nowcoder.com/practice/80b6bb8797644c83bc50ac761b72981c?tpId=196&tqId=37172&ru=/exam/oj
     */
    public boolean solve (String A, String B) {
        int n = A.length();
        int m = B.length();
        if(n != m) {
            return false;
        }
        String a = (A + A);
        return a.contains(B);
    }
}
